
#include "excel.h"

#include "..\engine\instr_db.h"
#include "..\engine\instr_dat.h"

#undef OPER_TYPE_REC
#define OPER_TYPE_REC(x) L#x,
//
// If new oper type is to be defined, go to oper_type.h
//
LPTSTR operand_type_name[]= {
#include "..\engine\oper_type_def.h"
L"unused"
} ;

#undef INSTR_REC
#define INSTR_REC(x) L#x,

LPTSTR instr_name[]= {
#include "..\engine\instr_id_def.h"
L"unused"
};

#undef FUNIT_REC
#define FUNIT_REC(x) L#x,

LPTSTR funit_name[]={
#include "..\engine\funit_def.h"
L"misc"
};


int Export(CExcelUtil &util,LPWSTR wsTableName, struct instr_rec *record, DWORD dwNumRecord);
int Import(CExcelUtil &util,LPWSTR wsTableName, FILE *fp,LPWSTR var_name);


#if 0
int main()
{
	CExcelUtil ExcelUtil;
	if (ExcelUtil.OpenEx(L"f:\\x86-inst.xls"))
	{
		Export(ExcelUtil,L"simpleinst",instr_recs, sizeof (instr_recs)/sizeof (instr_recs[0]));
		Export(ExcelUtil,L"complexinst",ext_instr_recs, sizeof (ext_instr_recs)/sizeof (ext_instr_recs[0]));

	}
	else
	{
		wprintf (L"Failed to create database.\n");
	}

	ExcelUtil.Close();
	return 0;
}
#else
int main()
{
	FILE *fp;
	CExcelUtil ExcelUtil;
	ExcelUtil.OpenEx(L"f:\\x86-inst.xls");

	fp = fopen("f:\\instr_dat.h","wt");
	if(fp)
	{
		fwprintf(fp,L"#ifndef __INSTR_H__\n"
			L"#define __INSTR_H__\n\n"
			L"\n\n"
			L"#include \"instr_db.h\"\n"
			L"#include \"operand.h\"\n\n" );

		Import(ExcelUtil,L"simpleinst",fp,L"instr_recs");
		Import(ExcelUtil,L"complexinst",fp,L"ext_instr_recs");

		fwprintf(fp,L"#endif    /*__INSTR_H__*/");
		fclose(fp);
	}
	ExcelUtil.Close();
	return 0;
}
#endif

int Export(CExcelUtil &util,LPWSTR wsTableName, struct instr_rec *record, DWORD dwNumRecord)
{
	CString sSql;

	sSql.Format(
			L"CREATE TABLE %s "
			L"(MNEM TEXT,ID TEXT,ID2 TEXT,IDMASK TEXT,WMASK TEXT,SMASK TEXT,DMASK TEXT,OP1 TEXT,OP2 TEXT,NAME TEXT, FUNIT TEXT );",
			wsTableName);
	try {
		util.ExecSql(sSql);
	} catch(CDBException *ex)
	{
		wprintf(L"%s",ex->m_strError);
	}

	try {
		for (DWORD i=0; i<dwNumRecord; i++) {
			WCHAR mnemonics[20];
			
			int j=0;
			char *s=record[i].mnemonics;

			while(*s) {mnemonics[j++]=*s++;}

			mnemonics[j]=0;

			sSql.Format(
				L"INSERT INTO %s "
				L"(MNEM, ID, ID2,IDMASK, WMASK, SMASK,DMASK,OP1,OP2,DST,NAME, FUNIT)"
				L"  VALUES('%s','0x%02X','0x%02X','0x%02X','%d','%d','%d','%s','%s','%s','%s','%s');",
				wsTableName,
				mnemonics,
				record[i].id,
				record[i].id2,
				record[i].mask,
				record[i].w_mask,
				record[i].sext_mask,
				record[i].dir_mask,
				operand_type_name[record[i].src1],
				operand_type_name[record[i].src2],
//				operand_type_name[record[i].dst],
				instr_name[record[i].index]
	//			funit_name[record[i].funit]
				);
			util.ExecSql(sSql);
		}
	}
	catch(CDBException *ex)
	{
		return 0;
	}
	return 1;
}

int Import(CExcelUtil &util,LPWSTR wsTableName, FILE *fp,LPWSTR var_name)
{
	CString sSql;

	fwprintf (fp,L"struct instr_rec %s[] = {\n",var_name);

	try {

		sSql.Format(L"Select * from %s;",wsTableName);

		util.OpenRecordSet (sSql);
		while (!util.IsEOF())
		{
			CString id = util.GetFieldValue(L"ID"); 
			CString id2 = util.GetFieldValue(L"ID2");
			CString id_mask = util.GetFieldValue(L"IDMASK"); 
			CString w_mask = util.GetFieldValue(L"WMASK");
			CString sext_mask = util.GetFieldValue(L"SMASK");
			CString dir_mask =util. GetFieldValue(L"DMASK");
			CString op1 = util.GetFieldValue(L"OP1");
			CString op2 = util.GetFieldValue(L"OP2");
			CString dst = util.GetFieldValue(L"DST");
			CString mnemonics = "\"" + util.GetFieldValue(L"MNEM");
			CString index = util.GetFieldValue(L"NAME");
			CString funit = util.GetFieldValue(L"FUNIT");

			util.NextRecord();
			fwprintf(fp,L"\t{%10s\", %5s, %5s, %5s, %5s, %5s, %5s, %8s, %8s, %8s, %8s,%8s }%c\n", 
				mnemonics,
				id,
				id_mask,
				id2,
				w_mask,
				sext_mask,
				dir_mask,
				op1,
				op2,
				dst,
				index,
				funit,
				util.IsEOF() ? L' ':L',');

		}
	}
	catch(...)
	{
		return 0;
	}
	fwprintf (fp,L"};\n\n");
	return 1;
}
#define CF 1
#define AF 2
#define PF 4
#define ZF 8
#define SF 16
#define OF 32

unsigned char flags_str_to_hex(const char * str)
{
	unsigned char flag = 0;
	while (*str)
	{
		switch (*str)
		{
		case 'o': case 'O':flag |= OF;break;
		case 's': case 'S':flag |= SF;break;
		case 'z': case 'Z':flag |= ZF;break;
		case 'p': case 'P':flag |= PF;break;
		case 'a': case 'A':flag |= AF;break;
		case 'c': case 'C':flag |= CF;break;
		}
	}
	return flag;
}

void flags_bin_to_str( unsigned char flag, char str[7])
{
	str[6]=0;
	str[5] = (flag&CF) ? 'c' :'-';
	str[4] = (flag&AF) ? 'a' :'-';
	str[3] = (flag&PF) ? 'p' :'-';
	str[2] = (flag&ZF) ? 'z' :'-';
	str[1] = (flag&SF) ? 's' :'-';
	str[0] = (flag&OF) ? 'o' :'-';
}